home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / freemacs.arc / REDISP.ASM < prev    next >
Assembly Source File  |  1988-03-17  |  37KB  |  1,619 lines

  1. ;History:457,1
  2.     .xlist
  3.  
  4. HT    equ    09h
  5. LF    equ    0ah
  6. CR    equ    0dh
  7. LINENEW    equ    CR+LF*256    ;the way a newline is stored in memory.
  8.  
  9. TRAIL_BLANK    equ    4dh
  10. TRAIL_TAB    equ    4eh
  11. MORE_CHAR    equ    52h
  12. NEWLINE_CHAR    equ    54h
  13.  
  14. bufseg    segment    byte public
  15.  
  16.     extrn    toptop: word
  17.     extrn    topbot: word
  18.     extrn    bottop: word
  19.     extrn    botbot: word
  20.  
  21.     extrn    linecount: word
  22.     extrn    linesbefore: word
  23.  
  24.     public    memsize
  25. memsize        dw    ?
  26.  
  27. bufseg    ends
  28.  
  29. data    segment    byte public
  30.  
  31.   if 1
  32.     public    w1, w2, this_point, this_row, other_row, topbotpercent
  33.     public    botpercent, toppercent, firstlimit, lastlimit, overwrite_row
  34.     public    overwrite_col, screen_column, window, inversed, inverse_mark
  35.     public    showblanks
  36.   endif
  37.  
  38. ;pointrow contains the row that the cursor is currently on, relative to the
  39. ;  screen boundaries.  Pointrow may be negative if the point is above the screen,
  40. ;  or it may be larger than max_screen_line if the point is below the screen.
  41.  
  42. wind_struc    struc
  43. windseg        dw    ?
  44. pointrow    dw    ?
  45. firstline    db    ?
  46. lastline    db    ?
  47. firstpossible    db    ?
  48. lastpossible    db    ?
  49. firstcolumn    dw    ?
  50. wind_struc    ends
  51.  
  52. w1    wind_struc<>
  53.  
  54. w2    wind_struc<>
  55.  
  56. this_point    dw    ?        ;->point in the current file.
  57. this_row    dw    ?        ;row of point on screen.
  58. other_row    dw    ?        ;row of point in other window.
  59.  
  60. topbotpercent    label    word
  61. botpercent    db    ?
  62. toppercent    db    ?
  63.  
  64. firstlastlimits    label    word
  65. firstlimit    db    ?
  66. lastlimit    db    ?
  67.  
  68.  
  69.     public    next_redisp_line
  70. next_redisp_line    dw    0
  71.  
  72.     public    overwrite_flag
  73. overwrite_flag    db    0        ;=0 if not overwriting.
  74.  
  75. overwrite_rowcol    label    word
  76. overwrite_row    db    0
  77. overwrite_col    db    0
  78.  
  79. ;the following externs are in the computer-dependent file
  80.     extrn    max_screen_line: byte
  81.  
  82. ;the following externs are in 'buffers'
  83.     extrn    textseg: word
  84.  
  85. screen_column    dw    ?
  86.  
  87. ;window contains a list of which lines should be moved where, and which
  88. ;  lines need to be redrawn.  If an entry is positive, then the line which is
  89. ;  currently at x belongs at window[x].  If an entry is TRASHED, it
  90. ;  should be redrawn.
  91. ;inversed contains a list of which lines currently show inverse video.
  92. window        db    50 dup(?)    ;50 is > max_screen_line
  93. inversed    db    50 dup(?)    ;. .
  94.     public    inversing
  95. inversing    dw    0
  96. inverse_mark    dw    ?
  97.     public    inverse_flag
  98. inverse_flag    db    0        ;=0 means no inversing.
  99. TRASHED        equ    -1        ;note that TRASHED must be negative.
  100.  
  101. showblanks    db    0
  102.  
  103. data    ends
  104.  
  105. b_struc    struc
  106. b    db    ?
  107. b_struc    ends
  108.  
  109. w_struc    struc
  110. w    dw    ?
  111. w_struc    ends
  112.  
  113. byte_ptr    label    byte
  114.  
  115. code    segment    byte public
  116. ;all the routines in this segment are entered with ds=data, es=data
  117.     assume    cs:code, ds:data, es:data
  118.  
  119.  
  120. ;the following externs are in the computer-dependent file.
  121.     extrn    move_line: near
  122.     extrn    clear_to_eol: near
  123.     extrn    xychrout: near
  124.     extrn    hardware_roll_up: near
  125.     extrn    hardware_roll_down: near
  126.     extrn    position_cursor: near
  127.  
  128.     extrn    xyputch: near
  129.  
  130. ;the following externs are in 'memory'
  131.     extrn    compute_cursor$: near
  132.     extrn    set_line$: near
  133.  
  134. ;the following externs are in 'buffers'
  135.     extrn    succ_buffer: near
  136.     extrn    buffer_number: near
  137.         ;enter with bx=paragraph of buffer.
  138.         ;exit with ax=number of buffer.
  139.     extrn    buffer_allocate: near
  140.     extrn    find_buffer: near
  141.         ;enter with cx=buffer number.
  142.         ;exit with nc, dx set to that buffer if it exists, cy otherwise.
  143.  
  144. ;the following externs are in 'marks'
  145.     extrn    read_mark$: near
  146.     extrn    goto_mark$: near
  147.     extrn    get_split_mark: near
  148.     extrn    get_mark: near
  149.     extrn    split_at_point: near
  150.     extrn    set_mark_si: near
  151.     extrn    set_mark: near
  152.     extrn    stack_marks: near
  153.     extrn    goto_mark: near
  154.  
  155.  
  156.     public    read_panes
  157. read_panes:
  158.     ret
  159.  
  160.  
  161.     public    read_current_window
  162. read_current_window:
  163.     mov    ax,1            ;probably window 1.
  164.     cmp    w2.windseg,0        ;no window 2 - must be 1.
  165.     je    read_current_window_1
  166.     mov    bl,w1.firstline
  167.     cmp    bl,w2.firstline
  168.     jb    read_current_window_1
  169.     inc    ax
  170. read_current_window_1:
  171.     ret
  172.  
  173.  
  174.     public    store_current_window
  175. store_current_window:
  176.     cmp    ax,1
  177.     jne    store_current_window_1
  178.     cmp    w2.windseg,0        ;is there a second window?
  179.     je    store_current_window_2    ;no - don't swap.
  180.     mov    al,w1.firstline
  181.     cmp    al,w2.firstline
  182.     jb    store_current_window_2
  183.     call    swap_other_row
  184.     call    swap_windows
  185.     jmp    short store_current_window_2
  186. store_current_window_1:
  187.     cmp    ax,2
  188.     jne    store_current_window_2
  189.     cmp    w2.windseg,0        ;is there a second window?
  190.     je    store_current_window_2    ;no - don't swap.
  191.     mov    al,w1.firstline
  192.     cmp    al,w2.firstline
  193.     ja    store_current_window_2
  194.     call    swap_other_row
  195.     call    swap_windows
  196. store_current_window_2:
  197.     ret
  198.  
  199.  
  200. swap_other_row:
  201.     mov    ax,w1.windseg        ;are we in the other window?
  202.     cmp    ax,w2.windseg
  203.     jne    swap_other_row_1    ;no - no worries.
  204.     push    w1.pointrow        ;remember what other_row will be.
  205.  
  206.     mov    ax,1
  207.     call    stack_marks
  208.     mov    ax,'*'*256+'0'        ;0 := *
  209.     call    set_mark
  210.     mov    ax,'.'*256+'*'        ;* := .
  211.     call    set_mark
  212.     mov    al,'0'            ;. := 0
  213.     call    goto_mark
  214.     mov    ax,0
  215.     call    stack_marks
  216.  
  217.     pop    other_row
  218. swap_other_row_1:
  219.     ret
  220.  
  221.  
  222.     public    read_other_window
  223. read_other_window:
  224.     mov    bx,w2.windseg
  225.     or    bx,bx
  226.     je    read_other_window_1
  227.     call    buffer_number
  228.     ret
  229. read_other_window_1:
  230.     xor    ax,ax
  231.     ret
  232.  
  233.  
  234.     public    store_other_window
  235. store_other_window:
  236. ;enter with ax=buffer segment to show.
  237.     mov    cx,ax            ;do they want one window?
  238.     jcxz    store_other_window_3    ;yes.
  239.     call    find_buffer        ;find the buffer.
  240.     jc    store_other_window_3    ;can't find it - give them one window.
  241.  
  242.     cmp    w2.windseg,0        ;do we have another window to set?
  243.     jne    store_other_window_1    ;yes - just set it.
  244.     push    dx
  245.     call    split_screen
  246.     pop    dx
  247. store_other_window_1:
  248.     cmp    dx,w2.windseg        ;is it already showing?
  249.     je    store_other_window_2    ;yes - they're being silly.
  250.  
  251.     mov    w2.windseg,dx        ;show the buffer here.
  252.  
  253.     cmp    w1.windseg,dx        ;is this buffer also in w1?
  254.     jne    store_other_window_4    ;no - no worries.
  255.  
  256.     mov    ax,w1.pointrow        ;the place that the this window is at
  257.     mov    other_row,ax        ;  becomes the other row.
  258.  
  259.     mov    ax,'.'*256+'*'        ;set the split mark to the point.
  260.     call    set_mark
  261.  
  262. store_other_window_4:
  263.     mov    bl,w2.firstline        ;trash what's there.
  264.     mov    al,w2.lastline
  265.     call    trash_some_lines
  266. store_other_window_2:
  267.     ret
  268.  
  269. store_other_window_3:
  270.     mov    w2.windseg,0
  271.     mov    al,max_screen_line    ;fill the screen with this window.
  272.     mov    w1.lastline,al
  273.     mov    w1.firstline,0
  274.     mov    si,offset w1
  275.     call    set_window_percent
  276.     call    paint_screen
  277.     ret
  278.  
  279.  
  280. split_screen:
  281.     mov    al,max_screen_line
  282.     mov    w2.lastline,al
  283.     sar    al,1
  284.     dec    al
  285.     mov    w1.lastline,al
  286.     add    al,2
  287.     mov    w2.firstline,al
  288.  
  289.     mov    si,offset w1
  290.     call    set_window_percent
  291.  
  292.     mov    si,offset w2
  293.     call    set_window_percent
  294.  
  295.     call    paint_screen
  296.  
  297.     ret
  298.  
  299.  
  300.     public    store_panes
  301. store_panes:
  302.     ret
  303.  
  304.  
  305.     public    store_showblanks
  306. store_showblanks:
  307.     cmp    showblanks,al        ;are we changing it?
  308.     mov    showblanks,al        ;store it in any case.
  309.     je    store_showblanks_1    ;if we changed it, paint the window.
  310.     call    paint_window
  311. store_showblanks_1:
  312.     ret
  313.  
  314.  
  315.     public    read_showblanks
  316. read_showblanks:
  317.     mov    al,showblanks
  318.     ret
  319.  
  320.  
  321.     public    read_firstline
  322. read_firstline:
  323.     mov    al,w1.firstline
  324.     ret
  325.  
  326.  
  327.     public    read_lastline
  328. read_lastline:
  329.     mov    al,w1.lastline
  330.     ret
  331.  
  332.  
  333.     public    read_newrow
  334. read_newrow:
  335.     mov    ax,w1.pointrow
  336.     ret
  337.  
  338.  
  339.     public    read_firstcolumn
  340. read_firstcolumn:
  341.     mov    ax,w1.firstcolumn
  342.     ret
  343.  
  344.  
  345.     public    read_top_percent
  346. read_top_percent:
  347.     mov    al,toppercent
  348.     ret
  349.  
  350.  
  351.     public    read_bot_percent
  352. read_bot_percent:
  353.     mov    al,botpercent
  354.     ret
  355.  
  356.  
  357.     public    store_top_percent
  358. store_top_percent:
  359.     mov    toppercent,al
  360.     mov    si,offset w1
  361.     call    set_window_percent
  362.     ret
  363.  
  364.  
  365.     public    store_bot_percent
  366. store_bot_percent:
  367.     mov    botpercent,al
  368.     mov    si,offset w1
  369.     call    set_window_percent
  370.     ret
  371.  
  372.  
  373.     public    init_screen
  374. init_screen:
  375.     xor    al,al
  376.     mov    w1.firstline,al
  377.     mov    w1.firstpossible,al
  378.     mov    al,max_screen_line    ;fill the screen with this window.
  379.     mov    w1.lastline,al
  380.     mov    w1.lastpossible,al
  381.     mov    w1.firstcolumn,0
  382.     mov    ax,textseg
  383.     mov    w1.windseg,ax
  384.     ret
  385.  
  386.  
  387.     public    gotoxy
  388. gotoxy:
  389.     cmp    dl,max_screen_line    ;is max_screen_line ok?
  390.     jbe    gotoxy_1        ;yes.
  391.     mov    dl,max_screen_line    ;no - take min(dl, max_screen_line)
  392. gotoxy_1:
  393.     cmp    dh,79            ;are we on the screen?
  394.     jbe    gotoxy_2
  395.     mov    dh,79            ;no - take min(dh, 79)
  396. gotoxy_2:
  397.     mov    overwrite_rowcol,dx
  398.     ret
  399.  
  400.  
  401.     public    chrout
  402. chrout:
  403. ;enter with ax=char to "type" on screen.
  404. ;preserve si.
  405.     cmp    overwrite_flag,0    ;are we already overwriting?
  406.     jne    chrout_1        ;yes.
  407.     mov    overwrite_flag,1    ;say that we're overwriting
  408.     mov    window[0],TRASHED    ;trash the first line.
  409. chrout_1:
  410.     mov    dx,overwrite_rowcol    ;get the cursor position.
  411.     cmp    al,CR            ;go to left margin?
  412.     jne    chrout_4
  413.     call    clear_to_eol        ;yes - clear to end here.
  414.     mov    dh,0
  415.     jmp    chrout_exit
  416. chrout_4:
  417.     cmp    al,LF            ;go down a line?
  418.     jne    chrout_5
  419.     inc    dl
  420.     cmp    dl,max_screen_line    ;are we past the last line?
  421.     jbe    chrout_exit        ;no.
  422.     call    hardware_roll_up    ;yes - roll the screen up.
  423.     jnc    chrout_6
  424.     mov    dl,1            ;have to software scroll.
  425. chrout_7:
  426.     mov    al,dl
  427.     dec    al
  428.     call    move_line
  429.     inc    dl
  430.     cmp    dl,max_screen_line
  431.     jbe    chrout_7
  432. chrout_6:
  433.     mov    dl,max_screen_line    ;say on the last line.
  434.     push    dx            ;clear the entire line.
  435.     mov    dh,0
  436.     call    clear_to_eol
  437.     pop    dx
  438.     jmp    short chrout_exit
  439. chrout_5:
  440.     cmp    al,HT
  441.     jne    chrout_8
  442. chrout_9:
  443.     mov    ah,0
  444.     mov    al,' '
  445.     call    chrout_putch
  446.     test    dh,7
  447.     jnz    chrout_9
  448.     jmp    short chrout_exit
  449. chrout_8:
  450.     call    chrout_putch
  451. chrout_exit:
  452.     mov    overwrite_rowcol,dx    ;remember where we are.
  453.     call    position_cursor
  454.     ret
  455.  
  456.  
  457. chrout_putch:
  458.     mov    bh,0            ;trash the line.
  459.     mov    bl,dl
  460.     mov    window[bx],TRASHED
  461.     call    xyputch
  462.     inc    dh
  463.     ret
  464.  
  465.  
  466.     public    redisplay
  467. redisplay:
  468.  
  469.     mov    ax,textseg        ;is the current buffer showing in w1?
  470.     cmp    ax,w1.windseg
  471.     je    redisplay$_1        ;yes - all ok.
  472.  
  473.     xchg    w1.windseg,ax        ;no - put it in this window.
  474.     cmp    ax,w2.windseg        ;was the old w1 showing in w2?
  475.     jne    redisplay$_2        ;no - nothing special.
  476.  
  477.     push    ds
  478.     mov    ds,w2.windseg
  479.     mov    al,'*'            ;yes - make the split mark the point
  480.     call    goto_mark$
  481.     pop    ds
  482.  
  483. redisplay$_2:
  484.  
  485.     mov    bl,w1.firstline
  486.     mov    al,w1.lastline
  487.     call    trash_some_lines
  488.  
  489.     mov    ax,w1.windseg        ;is this buffer also in w2?
  490.     cmp    ax,w2.windseg
  491.     jne    redisplay$_1        ;no - no worries.
  492.  
  493.     mov    bl,w2.firstline        ;yes - trash one line so that
  494.     mov    bh,0            ;  the point is recomputed.  hack, hack.
  495.     mov    window[bx],TRASHED
  496.  
  497.     mov    ax,w2.pointrow        ;the place that the other window is at
  498.     mov    other_row,ax        ;  becomes the other row.
  499.  
  500.     mov    ax,'.'*256+'*'        ;set the split mark to the point.
  501.     call    set_mark
  502.  
  503. redisplay$_1:
  504.  
  505.     mov    overwrite_flag,0    ;no longer overwriting.
  506.     mov    dx,0            ;start in the upper left hand corner
  507.     mov    overwrite_rowcol,dx    ;  the next time we overwrite.
  508.   if 0
  509.     mov    dx,0*256+24        ;dh=column, dl=row.
  510.     mov    si,offset window
  511. rd_0:
  512.     lodsb
  513.     add    al,'A'
  514.     call    xychrout
  515.     inc    dh
  516.     cmp    dh,25
  517.     jb    rd_0
  518.     mov    si,offset inversed
  519. rd_1:
  520.     lodsb
  521.     add    al,'0'
  522.     call    xychrout
  523.     inc    dh
  524.     cmp    dh,48
  525.     jb    rd_1
  526.  
  527.   endif
  528.  
  529.     push    ds
  530.     mov    ds,w1.windseg
  531.     assume    ds:bufseg
  532.  
  533.     mov    si,topbot
  534.     mov    this_point,si
  535.  
  536.     mov    ax,next_redisp_line
  537.  
  538.     call    force_point_into_window
  539.     mov    ax,w1.pointrow
  540.     mov    this_row,ax
  541.  
  542.     call    redraw_trashed
  543.  
  544.     mov    ax,this_row
  545.     mov    w1.pointrow,ax
  546.  
  547.     pop    ds
  548.     assume    ds:data
  549.  
  550.     mov    dx,screen_column
  551.     sub    dx,w1.firstcolumn
  552.     mov    dh,dl
  553.     mov    dl,byte ptr w1.pointrow
  554.     call    position_cursor
  555.  
  556.     cmp    w2.windseg,0        ;is there a second window?
  557.     je    redisplay_one        ;no.
  558.     call    swap_windows
  559.     push    ds
  560.     mov    ax,w1.windseg        ;are they the same file?
  561.     cmp    ax,w2.windseg
  562.     mov    ds,ax            ;really w2.
  563.     assume    ds:bufseg
  564.     jne    redisplay__2
  565. ;two windows into the same buffer.
  566.     call    get_split_mark        ;get the split mark.
  567.     cmp    si,bottop        ;are we at the point?
  568.     jne    redisplay__1        ;no.
  569.     mov    si,topbot        ;yes - always use the top point.
  570. redisplay__1:
  571.     mov    this_point,si
  572.     mov    ax,other_row        ;get the row in the other window.
  573.     mov    this_row,ax
  574.     call    redraw_trashed
  575.     mov    ax,this_row
  576.     xchg    other_row,ax
  577.     sub    ax,other_row        ;how much did we adjust it by?
  578.     sub    w1.pointrow,ax        ;adjust pointrow, too.
  579.  
  580.     jmp    short redisplay__3
  581. redisplay__2:
  582. ;two windows, two buffers.
  583.     mov    si,topbot
  584.     mov    this_point,si
  585.     xor    ax,ax
  586.     call    force_point_into_window
  587.     mov    ax,w1.pointrow
  588.     mov    this_row,ax
  589.     call    redraw_trashed
  590.  
  591. redisplay__3:
  592.     call    swap_windows
  593.     pop    ds
  594.     assume    ds:data
  595. redisplay_one:
  596.     mov    next_redisp_line,0    ;no more desired line
  597.     ret
  598.  
  599.  
  600. code    ends
  601.  
  602. code    segment    byte public
  603. ;all the code in this segment is entered with ds=bufseg, es=data
  604.     assume    cs:code, ds:bufseg, es:data
  605.  
  606.  
  607.     public    adjust_buffers
  608. adjust_buffers:
  609. ;enter with ds,bx=old buffer paragraph, ax=new buffer paragraph.
  610. ;exit with all registers undisturbed!
  611.     cmp    w1.windseg,bx        ;are we changing w1?
  612.     jne    adjust_buffers_1
  613.     mov    w1.windseg,ax
  614. adjust_buffers_1:
  615.     cmp    w2.windseg,bx        ;are we changing w2?
  616.     jne    adjust_buffers_2
  617.     mov    w2.windseg,ax
  618. adjust_buffers_2:
  619.     ret
  620.  
  621.  
  622. set_window_percent:
  623. ;note that set_window_percent doesn't use ds.
  624. ;enter with si->window to set.
  625.     mov    cl,100
  626.     mov    ch,data:[si].lastline
  627.     sub    ch,data:[si].firstline
  628.     inc    ch
  629.     mov    al,toppercent
  630.     mul    ch
  631.     div    cl
  632.     cmp    al,ch
  633.     jb    set_window_percent_1
  634.     xor    al,al
  635. set_window_percent_1:
  636.     add    al,data:[si].firstline
  637.     mov    data:[si].firstpossible,al
  638.     mov    al,botpercent
  639.     mul    ch
  640.     div    cl
  641.     mov    ch,data:[si].lastline
  642.     sub    ch,al
  643.     jae    set_window_percent_2
  644.     mov    ch,data:[si].lastline
  645. set_window_percent_2:
  646.     mov    data:[si].lastpossible,ch
  647.     ret
  648.  
  649.  
  650. roll_window_down_2_j_1:
  651.     jmp    roll_window_down_2
  652. roll_window_down_5_j_1:
  653.     jmp    roll_window_down_5
  654.  
  655. roll_window_down:
  656. ;roll the window down until pointrow is in the window.
  657.  
  658.     mov    al,firstlimit
  659.     cbw
  660.     cmp    w1.pointrow,ax        ;if pointrow>=firstlimit, we don't
  661.     jge    roll_window_down_2_j_1    ;  need to roll down.
  662.  
  663. ;Are there any lines now on the screen that will remain?  Go if not.
  664.  
  665.     mov    cx,w1.pointrow
  666.     mov    bh,0
  667.     mov    bl,w1.lastline
  668.     add    cx,bx
  669.     mov    bl,w1.firstline
  670.     sub    cx,bx
  671.     mov    bl,firstlimit
  672.     cmp    cx,bx
  673.     jl    roll_window_down_5_j_1    ;we have to repaint the entire window.
  674.  
  675.     mov    dx,w1.pointrow
  676.     mov    cl,w1.firstline
  677.     mov    ch,0
  678.     sub    dx,cx
  679.     inc    dx
  680.  
  681. ;now compute the number of times we need to roll.
  682.  
  683.     mov    cx,w1.pointrow
  684.     sub    cx,bx
  685.     mov    w1.pointrow,bx        ;bx is firstlimit
  686.     neg    cx
  687.  
  688. ;Can we use the hardware scroll?  Go if not.
  689.  
  690.     cmp    w1.firstline,0
  691.     jne    roll_window_down_3
  692.     mov    al,max_screen_line
  693.     cmp    w1.lastline,al
  694.     jne    roll_window_down_3
  695.  
  696. ;Use the hardware scroll unless there isn't one.
  697.  
  698.     xchg    cx,dx            ;get the distance to skip
  699.     call    skip_to_line
  700.     mov    cx,dx
  701.  
  702. roll_window_down_4:
  703.     call    hardware_roll_down
  704.     jc    roll_window_down_3    ;can't hardware roll.
  705.  
  706. ;now adjust window[] for the change we just made to the screen.
  707.  
  708.     mov    bl,w1.firstline
  709.     mov    bh,0
  710.     mov    al,window[bx]        ;save the current values for later.
  711.     mov    ah,inversed[bx]
  712.     push    ax
  713.     push    si
  714.     call    redraw_compare        ;remember if we're inversing here.
  715.     mov    inversed[bx],al
  716.     call    redraw_line
  717.     call    remember_redrawn
  718.     pop    si
  719.     call    prevline
  720.     mov    window[bx],bl        ;remember that this line is real.
  721.     pop    ax            ;restore the old values.
  722. roll_window_down_6:
  723.     cmp    al,TRASHED        ;is this a trashed line?
  724.     je    roll_window_down_7
  725.     inc    al            ;no - say that the line's moved up.
  726.     cmp    al,max_screen_line    ;did it roll off the screen?
  727.     jbe    roll_window_down_7    ;no.
  728.     mov    al,TRASHED        ;yes - it's gone.
  729. roll_window_down_7:
  730.     inc    bl
  731.     xchg    al,window[bx]
  732.     xchg    ah,inversed[bx]
  733.     cmp    bl,w1.lastline
  734.     jb    roll_window_down_6
  735.     loop    roll_window_down_4
  736.     jmp    short roll_window_down_2
  737.  
  738. ;repaint screen.
  739.  
  740. roll_window_down_5:
  741.     call    center_this
  742.     jmp    short roll_window_down_2
  743.  
  744. ;Use software scroll.  All we do is roll the window array.
  745.  
  746. roll_window_down_3:
  747.     mov    bl,w1.firstline
  748.     mov    bh,0
  749.     mov    al,window[bx]        ;save the current value for later.
  750.     mov    ah,inversed[bx]
  751.     mov    window[bx],TRASHED
  752. roll_window_down_1:
  753.     inc    bl
  754.     xchg    al,window[bx]
  755.     xchg    ah,inversed[bx]
  756.     cmp    bl,w1.lastline
  757.     jb    roll_window_down_1
  758.     loop    roll_window_down_3
  759. roll_window_down_2:
  760.     ret
  761.  
  762.  
  763. roll_window_up_2_j_1:
  764.     jmp    roll_window_up_2
  765.  
  766. roll_window_up:
  767.  
  768.     mov    al,lastlimit
  769.     cbw
  770.     cmp    w1.pointrow,ax        ;if pointrow<=lastlimit, we don't
  771.     jle    roll_window_up_2_j_1    ;  need to roll up.
  772.  
  773. ;compute: pointrow-(lastline-firstline) > lastlimit
  774.  
  775. ;Are there any lines now on the screen that will remain?  Go if not.
  776.  
  777.     mov    cx,w1.pointrow
  778.     mov    bh,0
  779.     mov    bl,w1.firstline
  780.     add    cx,bx
  781.     mov    bl,w1.lastline
  782.     sub    cx,bx
  783.     mov    bl,lastlimit
  784.     cmp    cx,bx
  785.     jg    roll_window_up_5    ;we have to repaint the entire window.
  786.  
  787.     mov    dx,w1.pointrow
  788.     mov    cl,w1.lastline
  789.     mov    ch,0
  790.     sub    dx,cx
  791.     dec    dx
  792.  
  793. ;now compute the number of times we need to roll.
  794.  
  795.     mov    cx,w1.pointrow
  796.     sub    cx,bx
  797.     mov    w1.pointrow,bx        ;bx is lastlimit.
  798.  
  799. ;Can we use hardware scroll?  Go if not.
  800.  
  801.     cmp    w1.firstline,0
  802.     jne    roll_window_up_3
  803.     mov    al,max_screen_line
  804.     cmp    w1.lastline,al
  805.     jne    roll_window_up_3
  806.  
  807. ;Use the hardware scroll unless there isn't one.
  808.  
  809.     xchg    cx,dx            ;get the distance to skip
  810.     call    skip_to_line
  811.     mov    cx,dx
  812.  
  813. roll_window_up_4:
  814.     call    hardware_roll_up
  815.     jc    roll_window_up_3    ;can't hardware roll.
  816.  
  817. ;now adjust window[] for the change we just made to the screen.
  818.  
  819.     mov    bl,w1.lastline
  820.     mov    bh,0
  821.     mov    al,window[bx]        ;save the current values for later.
  822.     mov    ah,inversed[bx]
  823.     push    ax
  824.     call    redraw_compare        ;remember if we're inversing here.
  825.     mov    inversed[bx],al
  826.     call    redraw_line
  827.     call    remember_redrawn
  828.     mov    window[bx],bl        ;remember that this line is real.
  829.     pop    ax            ;restore old values.
  830. roll_window_up_6:
  831.     cmp    al,TRASHED        ;has this line been trashed?
  832.     je    roll_window_up_7
  833.     dec    al            ;no - say the line's been moved.
  834. roll_window_up_7:
  835.     dec    bl
  836.     xchg    al,window[bx]
  837.     xchg    ah,inversed[bx]
  838.     cmp    bl,w1.firstline
  839.     ja    roll_window_up_6
  840.     loop    roll_window_up_4
  841.     jmp    short roll_window_up_2
  842.  
  843. ;repaint screen.
  844.  
  845. roll_window_up_5:
  846.     call    center_this
  847.     jmp    short roll_window_up_2
  848.  
  849. ;Use software scroll.  All we do is roll the window array.
  850.  
  851. roll_window_up_3:
  852.     mov    bl,w1.lastline
  853.     mov    bh,0
  854.     mov    al,window[bx]        ;save the current value for later.
  855.     mov    ah,inversed[bx]
  856.     mov    window[bx],TRASHED
  857. roll_window_up_1:
  858.     dec    bl
  859.     xchg    al,window[bx]
  860.     xchg    ah,inversed[bx]
  861.     cmp    bl,w1.firstline
  862.     ja    roll_window_up_1
  863.     loop    roll_window_up_3
  864. roll_window_up_2:
  865.     ret
  866.  
  867.  
  868. ;enter with pointrow=current relative screen line
  869. ;exit with a line inserted before pointrow.
  870.     public    window_insert
  871. window_insert:
  872.     push    si
  873.     mov    ax,ds            ;is this in window 1?
  874.     cmp    ax,w1.windseg
  875.     jne    window_insert_1
  876.     mov    si,offset w1
  877.     call    window_ins
  878. window_insert_1:
  879.     mov    ax,ds            ;is this in window 2?
  880.     cmp    ax,w2.windseg
  881.     jne    window_insert_2
  882.     mov    si,offset w2
  883.     call    window_ins
  884. window_insert_2:
  885.     mov    ax,ds            ;are we showing in both windows?
  886.     cmp    ax,w1.windseg
  887.     jne    window_insert_3
  888.     cmp    ax,w2.windseg
  889.     jne    window_insert_3
  890.     call    split_at_point        ;is the split mark at or after the point?
  891.     jnc    window_insert_3        ;no
  892.     inc    other_row        ;yes - must increment the other row.
  893. window_insert_3:
  894.     pop    si
  895.     ret
  896.  
  897. ;private subroutine, called by window_insert to insert a line in a window.
  898. ;enter with si-> a window structure.
  899. window_ins:
  900.     mov    bx,data:[si].pointrow
  901.     mov    al,data:[si].firstline
  902.     cbw
  903.     cmp    bx,ax            ;are we above the screen?
  904.     jl    window_ins_3        ;yes - exit.
  905.     mov    al,data:[si].lastline
  906.     cmp    bx,ax            ;are we below the screen?
  907.     jg    window_ins_2        ;yes - go down a row.
  908.  
  909.     mov    window[bx],TRASHED
  910.     mov    al,TRASHED
  911.     jmp    short window_ins_4
  912. window_ins_1:
  913.     xchg    al,window[bx]
  914.     xchg    ah,inversed[bx]
  915. window_ins_4:
  916.     inc    bl
  917.     cmp    bl,data:[si].lastline
  918.     jbe    window_ins_1
  919. window_ins_2:
  920.     inc    data:[si].pointrow
  921. window_ins_3:
  922.     ret
  923.  
  924.  
  925. ;enter with pointrow=current relative screen line
  926. ;exit with the line at pointrow deleted.
  927.     public    window_delete
  928. window_delete:
  929.     push    si
  930.     mov    ax,ds            ;is this in window 1?
  931.     cmp    ax,w1.windseg
  932.     jne    window_delete_1
  933.     mov    si,offset w1
  934.     call    window_del
  935. window_delete_1:
  936.     mov    ax,ds            ;is this in window 2?
  937.     cmp    ax,w2.windseg
  938.     jne    window_delete_2
  939.     mov    si,offset w2
  940.     call    window_del
  941. window_delete_2:
  942.     mov    ax,ds            ;are we showing in both windows?
  943.     cmp    ax,w1.windseg
  944.     jne    window_delete_3
  945.     cmp    ax,w2.windseg
  946.     jne    window_delete_3
  947.     call    split_at_point        ;is the split mark at or after the point?
  948.     jnc    window_delete_3        ;no
  949.     dec    other_row        ;yes - must decrement the other row.
  950. window_delete_3:
  951.     pop    si
  952.     ret
  953.  
  954. ;private subroutine, called by window_delete to delete a line from a window.
  955. ;enter with si-> a window structure.
  956. window_del:
  957.     mov    bx,data:[si].pointrow
  958.     mov    al,data:[si].firstline
  959.     cbw
  960.     cmp    bx,ax            ;are we above the screen?
  961.     jl    window_del_4        ;yes.
  962.     mov    al,data:[si].lastline
  963.     cbw
  964.     cmp    bx,ax            ;are we below the screen?
  965.     jg    window_del_1        ;yes.
  966.  
  967.     mov    window[bx],TRASHED    ;kill the line the cursor is on.
  968.     jmp    short window_del_5    ;go into while...do loop
  969. window_del_4:
  970.     inc    data:[si].pointrow
  971.     jmp    short window_del_1
  972. window_del_3:
  973.     mov    al,window[bx+1]
  974.     mov    ah,inversed[bx+1]
  975.     mov    window[bx],al
  976.     mov    inversed[bx],ah
  977. window_del_5:
  978.     inc    bl
  979.     cmp    bl,data:[si].lastline
  980.     jb    window_del_3
  981.     mov    window[bx],TRASHED    ;kill lastline
  982. window_del_1:
  983.     ret
  984.  
  985.  
  986.     public    trash_line
  987. trash_line:
  988. ;destroy the line that the point is on if it's also in the window.
  989.     mov    ax,ds            ;is this in window 1?
  990.     cmp    ax,w1.windseg
  991.     jne    trash_line_1
  992.     mov    si,offset w1
  993.     call    trash_line_0
  994. trash_line_1:
  995.     mov    ax,ds            ;is this in window 2?
  996.     cmp    ax,w2.windseg
  997.     jne    trash_line_2
  998.     mov    si,offset w2
  999.     call    trash_line_0
  1000. trash_line_2:
  1001.     ret
  1002.  
  1003.  
  1004. ;enter with si-> a window structure.
  1005. trash_line_0:
  1006.     mov    bx,data:[si].pointrow
  1007.     mov    al,data:[si].firstline
  1008.     cbw
  1009.     cmp    bx,ax
  1010.     jl    trash_line_3
  1011.     mov    al,data:[si].lastline
  1012.     cbw
  1013.     cmp    bx,ax
  1014.     jg    trash_line_3
  1015.     mov    window[bx],TRASHED
  1016. trash_line_3:
  1017.     ret
  1018.  
  1019.  
  1020.     public    up_lines
  1021. up_lines:
  1022.     mov    ax,ds            ;is this in window 2?
  1023.     cmp    ax,w1.windseg
  1024.     jne    up_lines_1
  1025.     sub    w1.pointrow,bx
  1026. up_lines_1:
  1027.     mov    ax,ds            ;is this in window 2?
  1028.     cmp    ax,w2.windseg
  1029.     jne    up_lines_2
  1030.     sub    w2.pointrow,bx
  1031. up_lines_2:
  1032.     ret
  1033.  
  1034.  
  1035.     public    down_lines
  1036. down_lines:
  1037.     mov    ax,ds            ;is this in window 1?
  1038.     cmp    ax,w1.windseg
  1039.     jne    down_lines_1
  1040.     add    w1.pointrow,bx
  1041. down_lines_1:
  1042.     mov    ax,ds            ;is this in window 2?
  1043.     cmp    ax,w2.windseg
  1044.     jne    down_lines_2
  1045.     add    w2.pointrow,bx
  1046. down_lines_2:
  1047.     ret
  1048.  
  1049.  
  1050.     public    paint_screen
  1051. paint_screen:
  1052. ;note that paint doesn't use ds.
  1053. ;what's on the screen is garbage.
  1054. ;preserve si, dx.
  1055.     mov    bl,0
  1056.     mov    al,max_screen_line
  1057.     call    trash_some_lines
  1058.     ret
  1059.  
  1060.  
  1061. center_window:
  1062. ;note that center doesn't use ds.
  1063. ;preserve dx.
  1064. center_this:
  1065.     mov    cl,w1.lastline        ;compute the middle of the screen.
  1066.     sub    cl,w1.firstline
  1067.     sar    cl,1
  1068.     add    cl,w1.firstline
  1069.     mov    ch,0
  1070.     mov    w1.pointrow,cx
  1071.     mov    bl,w1.firstline
  1072.     mov    al,w1.lastline
  1073.     call    trash_some_lines
  1074.     ret
  1075.  
  1076.  
  1077.     public    paint_window
  1078. paint_window:
  1079. ;preserve dx.
  1080.     mov    ax,textseg
  1081.     cmp    ax,w1.windseg
  1082.     jne    paint_window_1
  1083.     mov    bl,w1.firstline
  1084.     mov    al,w1.lastline
  1085.     call    trash_some_lines
  1086. paint_window_1:
  1087.     mov    ax,textseg
  1088.     cmp    ax,w2.windseg
  1089.     jne    paint_window_2
  1090.     mov    bl,w2.firstline
  1091.     mov    al,w2.lastline
  1092.     call    trash_some_lines
  1093. paint_window_2:
  1094.     ret
  1095.  
  1096.  
  1097. trash_some_lines:
  1098. ;enter with bl=first line to destroy, al=last line.
  1099. ;preserve si, dx.
  1100.     mov    w1.firstcolumn,0    ;go to the first column.
  1101.     mov    bh,0
  1102. trash_some_lines_0:
  1103.     mov    window[bx],TRASHED
  1104.     inc    bl
  1105.     cmp    bl,al
  1106.     jbe    trash_some_lines_0
  1107.     mov    al,w1.firstpossible    ;ensure that we're not above the screen.
  1108.     cbw
  1109.     cmp    w1.pointrow,ax
  1110.     jge    trash_some_lines_1    ;we're not.
  1111.     mov    w1.pointrow,ax
  1112. trash_some_lines_1:
  1113.     mov    al,w1.lastpossible    ;ensure that we're not below the screen.
  1114.     cbw
  1115.     cmp    w1.pointrow,ax
  1116.     jle    trash_some_lines_2    ;we're not.
  1117.     mov    w1.pointrow,ax
  1118. trash_some_lines_2:
  1119.     ret
  1120.  
  1121.  
  1122. ;swap the two window data structures.
  1123. swap_windows:
  1124.     mov    si,offset w1
  1125.     mov    di,offset w2
  1126.     mov    cx,(size wind_struc)
  1127. swap_windows_0:
  1128.     mov    al,data:[si]
  1129.     xchg    al,data:[di]
  1130.     mov    data:[si],al
  1131.     inc    si
  1132.     inc    di
  1133.     loop    swap_windows_0
  1134.     ret
  1135.  
  1136.  
  1137. force_point_into_window:
  1138. ;enter with al=the desired row, =0 if we don't care.
  1139. comment /**********************************************************************
  1140. * roll the window array until pointrow is on the screen.
  1141. * when we roll the array, the lines we roll in must be repainted.
  1142. * for example, assume: screen is 0..23
  1143. * if pointrow is     5, then we're done.
  1144. * if pointrow is    -7, then we must roll down 7 lines.
  1145. * if pointrow is <=-24, then we must roll down 24 lines, which says that the
  1146. *                     entire screen will be repainted.
  1147. * if pointrow is    27, then we must roll up 3 lines.
  1148. * if pointrow is  >=48, then we must roll up 24 lines, which says that the
  1149. *                  entire screen will be repainted.
  1150. *****************************************************************************/
  1151.     mov    bl,w1.firstpossible
  1152.     mov    bh,w1.lastpossible
  1153.     or    al,al            ;do we have a desired row?
  1154.     je    redisplay_1        ;no.
  1155.     dec    al
  1156.     cmp    al,bl            ;above firstpossible?
  1157.     ja    redisplay_0        ;yes - ok.
  1158.     mov    al,bl            ;no - clip to firstpossible.
  1159. redisplay_0:
  1160.     cmp    al,bh            ;below lastpossible?
  1161.     jb    redisplay_00        ;yes - ok.
  1162.     mov    al,bh            ;no - clip to lastpossible.
  1163. redisplay_00:
  1164.     mov    bl,al
  1165.     mov    bh,al
  1166. redisplay_1:
  1167.     mov    firstlastlimits,bx
  1168. ;now truncate firstlimit if we can't get there.
  1169.     mov    al,firstlimit
  1170.     cbw                ;compute the number of display lines
  1171.     sub    al,w1.firstline        ;  desired before the cursor line.
  1172.     cmp    ax,linesbefore        ;is it even possible to get there?
  1173.     jb    redisplay_2        ;yes - just do it.
  1174.     mov    ax,linesbefore        ;no - truncate firstlimit to
  1175.     add    al,w1.firstline        ;  the largest possible.
  1176.     mov    firstlimit,al
  1177. redisplay_2:
  1178.  
  1179. ;Now update row,col
  1180.  
  1181.     call    compute_cursor$
  1182.     mov    screen_column,dx
  1183.     sub    dx,w1.firstcolumn    ;are we to the left of the screen?
  1184.     jb    redisplay_01        ;yes - must roll the screen right.
  1185.     cmp    dx,80            ;are we on the screen?
  1186.     jb    redisplay_02        ;yes - we don't have the roll left.
  1187.  
  1188. ;roll the window to the left.
  1189.  
  1190. comment /
  1191. Eventually, we'll be smart about all this and really scroll the screen.
  1192. For now, we'll repaint the screen every time we roll.
  1193.     jmp    short redisplay_02
  1194. /
  1195.  
  1196. redisplay_01:
  1197.  
  1198. ;roll the window to the right.
  1199.  
  1200. comment /
  1201. Eventually, we'll be smart about all this and really scroll the screen.
  1202. For now, we'll repaint the screen every time we roll.
  1203. /
  1204.  
  1205.     add    dx,w1.firstcolumn    ;restore the cursor position.
  1206.     mov    bl,w1.firstline
  1207.     mov    al,w1.lastline
  1208.     call    trash_some_lines
  1209.     and    dl,not 7        ;back up to previous tab stop.
  1210.     sub    dx,40            ;put the cursor in middle of screen.
  1211.     jae    redisplay_03
  1212.     mov    dx,0            ;column is less than 40.
  1213. redisplay_03:
  1214.     mov    w1.firstcolumn,dx    ;that is where we start redisplaying.......................
  1215. redisplay_02:
  1216.  
  1217. ;now roll the screen up or down, as needed.
  1218.  
  1219.     call    roll_window_down
  1220.     call    roll_window_up
  1221.     ret
  1222.  
  1223.  
  1224. redraw_trashed:
  1225. ;redraw all changed lines if there are any to redraw.
  1226. redraw_trashed_4:
  1227.     mov    bl,w1.firstline
  1228.     mov    bh,0
  1229.     mov    dh,0            ;initially, we don't need to redraw any.
  1230. redraw_trashed_3:
  1231.     mov    dl,window[bx]        ;get new window contents.
  1232.     or    dh,dl            ;remember if we need to redraw any.
  1233.     or    dl,dl            ;if positive, it's a line to be moved.
  1234.     js    redraw_trashed_5        ;if negative, skip it.
  1235.     cmp    dl,bl            ;is the line already there?
  1236.     je    redraw_trashed_5        ;yes - skip it.
  1237.     mov    di,offset window    ;is this row referred to?
  1238.     mov    cl,max_screen_line
  1239.     inc    cl
  1240.     mov    ch,0
  1241.     mov    al,bl
  1242.     repne    scasb            ;scan for the row.
  1243.     je    redraw_trashed_5        ;yes - we can't move something here.
  1244.     call    move_line        ;move dl to al.
  1245.     mov    dh,0            ;get the source line.
  1246.     mov    di,dx
  1247.     mov    al,inversed[di]        ;transfer the inversed contents.
  1248.     mov    inversed[bx],al
  1249.     mov    window[bx],bl        ;say that this line is where it is.
  1250.     jmp    redraw_trashed_4        ;restart search.
  1251. redraw_trashed_5:
  1252.     inc    bl
  1253.     cmp    bl,w1.lastline
  1254.     jbe    redraw_trashed_3
  1255.  
  1256.     cmp    inverse_flag,0        ;if we're inversing, we might need to redraw.
  1257.     jne    redraw_trashed_1
  1258.     or    dh,dh            ;do we need to redraw any lines?
  1259.     jns    redraw_trashed_9        ;no.
  1260.  
  1261. redraw_trashed_1:
  1262.     mov    bl,w1.firstline
  1263.     mov    bh,0
  1264.     mov    cx,this_row        ;get the row that the point is on.
  1265.     sub    cx,bx
  1266.     call    skip_to_line        ;find the first line on the screen.
  1267.     call    redraw_anyway        ;see if we need to redraw anyway.
  1268. redraw_trashed_7:
  1269.     call    redraw_compare        ;remember if we're inversing here.
  1270.     mov    inversed[bx],al
  1271.     cmp    window[bx],0
  1272.     jns    redraw_trashed_a        ;if negative, redraw it.
  1273.     call    redraw_line
  1274.     mov    window[bx],bl        ;remember that this line is drawn.
  1275. redraw_trashed_a:
  1276.     call    remember_redrawn
  1277.     inc    bl
  1278.     cmp    bl,w1.lastline
  1279.     jbe    redraw_trashed_7
  1280. redraw_trashed_9:
  1281.     mov    inversing,0        ;say that we're not inversing.
  1282.     ret
  1283.  
  1284.  
  1285. remember_redrawn:
  1286. ;enter with si->text, bx=screen line.
  1287. ;exit with si->next line.
  1288.     call    nextline
  1289.     shl    inversed[bx],1
  1290.     shl    inversed[bx],1
  1291.     call    redraw_compare
  1292.     or    inversed[bx],al
  1293.     ret
  1294.  
  1295.  
  1296. redraw_anyway:
  1297. ;preserve si,bx.
  1298.     cmp    inverse_flag,0
  1299.     je    redraw_anyway_1
  1300.     push    si
  1301.     push    bx
  1302. redraw_anyway_2:
  1303.     call    redraw_compare
  1304.     push    ax
  1305.     call    nextline        ;see if this line contains the mark or point.
  1306.     call    redraw_compare
  1307.     pop    cx
  1308.     mov    ch,cl            ;save a copy.
  1309.     xor    cl,al            ;see if the bits changed.
  1310.     test    cl,1            ;is the point in this line?
  1311.     jne    redraw_anyway_yes    ;yes - must redraw.
  1312.     shl    ch,1
  1313.     shl    ch,1
  1314.     or    al,ch            ;make up the compare byte.
  1315.     cmp    al,inversed[bx]        ;have they changed?
  1316.     je    redraw_anyway_no    ;no - don't necessarily redraw.
  1317. redraw_anyway_yes:
  1318.     mov    window[bx],TRASHED    ;say that this line is gone.
  1319. redraw_anyway_no:
  1320.     inc    bl
  1321.     cmp    bl,w1.lastline
  1322.     jbe    redraw_anyway_2
  1323.     pop    bx
  1324.     pop    si
  1325. redraw_anyway_1:
  1326.     ret
  1327.  
  1328.  
  1329. redraw_compare:
  1330. ;enter with si->text buffer.
  1331. ;exit with al and 1 = 1 if si<point,
  1332. ;          al and 2 = 2 if si<mark.
  1333.     cmp    si,inverse_mark        ;set cy if si is below inverse_mark (mark)
  1334.     rcl    al,1
  1335.     cmp    si,bottop        ;set cy if si is below bottop (point)
  1336.     rcl    al,1
  1337.     and    al,3            ;get rid of other bits.
  1338.     ret
  1339.  
  1340.  
  1341.  
  1342. skip_to_line:
  1343. ;enter with cx=number of lines to move forward or backward.
  1344. ;Note: positive values move toward top of file.
  1345. ;return si -> beginning of desired line.
  1346. ;don't destroy dx.
  1347.     mov    si,this_point        ;get the point.
  1348.     or    cx,cx            ;is cx negative?
  1349.     js    skip_to_line_4        ;yes - we have to move forward.
  1350.     cmp    [si-2].w,LINENEW    ;if we're not at the beginning of
  1351.     je    skip_to_line_3        ;  this line, backup to beginning.
  1352.     call    prevline
  1353. skip_to_line_3:
  1354.     jcxz    skip_to_line_2
  1355. skip_to_line_1:
  1356.     call    prevline
  1357.     loopne    skip_to_line_1
  1358.     jne    skip_to_line_2        ;did we hit the beginning?
  1359.     inc    cx            ;yes - restore the count.
  1360.     sub    this_row,cx        ;adjust this row.
  1361.     jmp    short skip_to_line_2
  1362. skip_to_line_4:
  1363.     neg    cx            ;make cx into a positive count.
  1364.                     ;cx is at least one.
  1365. skip_to_line_5:
  1366.     call    nextline
  1367.     loopne    skip_to_line_5
  1368. skip_to_line_2:
  1369.     mov    al,inverse_flag        ;are we inversing?
  1370.     cmp    al,0
  1371.     je    skip_to_line_6        ;no.
  1372.     push    bx
  1373.     push    dx
  1374.     push    si
  1375.     call    get_mark        ;the mark is in inverse_flag
  1376.     mov    inverse_mark,si        ;remember where the inverse mark is.
  1377.     pop    si
  1378.     pop    dx
  1379.     pop    bx
  1380. skip_to_line_6:
  1381.     ret
  1382.  
  1383.  
  1384. redraw_line:
  1385. ;enter with si -> line to be redrawn, bl=row of line.
  1386. ;paint from firstcolumn for 80 columns.
  1387. ;this routine is intense.
  1388. ;preserve cx, bx
  1389.     call    redraw_set
  1390.     mov    di,0            ;start at column zero.
  1391.     mov    dh,0
  1392.     mov    dl,bl
  1393.     mov    bl,-1            ;start without trailing blanks.
  1394.     cmp    si,botbot        ;are we at bottom already?
  1395.     je    redraw_line_9_j_1    ;yes - clear to eol.
  1396. redraw_line_2:
  1397.     call    redraw_pointer
  1398.     mov    ax,[si]
  1399.     cmp    ax,LINENEW        ;done with line?
  1400.     je    redraw_line_3        ;yes - exit.
  1401.     inc    si
  1402.     cmp    dh,79            ;at right hand column?
  1403.     ja    redraw_line_d        ;yes - don't print.
  1404.     cmp    di,w1.firstcolumn    ;before first column?
  1405.     jb    redraw_line_4        ;yes - just compute new column.
  1406.     cmp    al,' '            ;possible trailing blanks.
  1407.     je    redraw_line_a
  1408.     cmp    al,HT
  1409.     jne    redraw_line_b        ;not trailing blanks - forget.
  1410. redraw_line_a:
  1411.     cmp    bl,-1            ;are we already remembering?
  1412.     jne    redraw_line_c        ;yes - don't remember again.
  1413.     mov    bl,dh            ;found a trailing blank character,
  1414.     mov    bp,si            ;  remember where it was.
  1415.     jmp    short redraw_line_c
  1416. redraw_line_b:
  1417.     mov    bl,-1            ;printable char - forget trailing blanks.
  1418. redraw_line_c:
  1419.     call    xy_char_put
  1420.     jmp    redraw_line_2
  1421. redraw_line_d:
  1422.     cmp    dh,80            ;did we just get there?
  1423.     ja    redraw_line_2        ;no.
  1424.     dec    dh
  1425.     mov    ax,8*256+MORE_CHAR    ;yes - print the "more" symbol.
  1426.     call    xychrout
  1427.     mov    dh,81            ;say that we're in the next column.
  1428.     jmp    redraw_line_2
  1429. redraw_line_4:
  1430.     inc    di
  1431.     cmp    al,HT            ;only tabs are special
  1432.     jne    redraw_line_2
  1433.     mov    ax,di
  1434.     add    ax,7            ;round up to next tab stop.
  1435.     and    al,not 7
  1436.     mov    di,ax
  1437.     jmp    redraw_line_2
  1438. redraw_line_9_j_1:
  1439.     jmp    redraw_line_9
  1440. redraw_line_3:
  1441.     cmp    showblanks,0        ;should we show blanks?
  1442.     je    redraw_line_8
  1443.     cmp    bl,-1            ;are there any trailing blanks?
  1444.     je    redraw_line_8        ;no.
  1445.     mov    dh,bl            ;restore the column.
  1446.     xchg    si,bp            ;save the current and restore the old.
  1447.     dec    si
  1448.     call    redraw_set
  1449. redraw_line_7:
  1450.     call    redraw_pointer
  1451.     mov    ax,[si]            ;get the next char.
  1452.     cmp    ax,LINENEW
  1453.     je    redraw_line_e
  1454.     cmp    dh,79
  1455.     ja    redraw_line_e
  1456.     inc    si
  1457.     cmp    al,' '            ;it can only be a tab or a space.
  1458.     je    redraw_line_6        ;must be a space.
  1459. redraw_line_5:
  1460.     mov    ax,8*256+TRAIL_TAB    ;output a trailing tab char.
  1461.     call    xychrout
  1462.     inc    dh
  1463.     test    dh,7            ;at a tab stop yet?
  1464.     jne    redraw_line_5        ;no.
  1465.     jmp    redraw_line_7
  1466. redraw_line_6:                ;output a trailing blank char.
  1467.     mov    ax,8*256+TRAIL_BLANK
  1468.     call    xychrout
  1469.     inc    dh
  1470.     jmp    redraw_line_7
  1471. redraw_line_e:
  1472.     mov    si,bp            ;restore the text pointer.
  1473. redraw_line_8:
  1474.     cmp    dh,80            ;put a newline symbol if there's room.
  1475.     jae    redraw_line_9
  1476.     cmp    inversing,0        ;only if we're inversing.
  1477.     je    redraw_line_9
  1478.     mov    ax,8*256+NEWLINE_CHAR    ;newline symbol.
  1479.     call    xychrout
  1480.     inc    dh
  1481. redraw_line_9:
  1482.     call    clear_to_eol
  1483.     mov    bh,0            ;restore bx.
  1484.     mov    bl,dl
  1485.     ret
  1486.  
  1487.  
  1488. redraw_pointer:
  1489. ;adjust si from the top to the bottom if necessary, and adjust inversing.
  1490.     cmp    si,topbot        ;at the point yet?
  1491.     jne    redraw_pointer_1    ;no.
  1492.     mov    si,bottop
  1493.     cmp    inverse_flag,0        ;are we inversing?
  1494.     je    redraw_pointer_1    ;no.
  1495.     not    inversing        ;say that we've passed the point.
  1496. redraw_pointer_1:
  1497.     cmp    si,inverse_mark        ;are we at the inverse mark?
  1498.     jne    redraw_pointer_2    ;yes - maybe inverse.
  1499.     cmp    inverse_flag,0        ;are we inversing?
  1500.     je    redraw_pointer_2    ;no.
  1501.     not    inversing        ;say that we've passed the point.
  1502. redraw_pointer_2:
  1503.     ret
  1504.  
  1505.  
  1506. redraw_set:
  1507.     cmp    inverse_flag,0        ;if we're not inversing, don't inverse.
  1508.     je    redraw_set_1
  1509.     call    redraw_compare
  1510.     cmp    si,inverse_mark        ;are we exactly at the mark?
  1511.     jne    redraw_set_2        ;no - just check parity.
  1512.     xor    al,2            ;yes - flip the associated bit.
  1513. redraw_set_2:
  1514.     mov    inversing,0        ;say that we're not inversing.
  1515.     or    al,al            ;look for 00,11 or 10,01
  1516.     jpe    redraw_set_1        ;go if not within point and mark.
  1517.     not    inversing        ;say that we're inversing.
  1518. redraw_set_1:
  1519.     ret
  1520.  
  1521.  
  1522. xy_char_put:
  1523. ;put a char on the screen.  Interpret tabs.
  1524.     cmp    al,HT
  1525.     jne    xy_char_put_1
  1526. xy_char_put_2:
  1527.     mov    al,' '
  1528.     call    xy_char_put_1
  1529.     test    dh,7
  1530.     jnz    xy_char_put_2
  1531.     ret
  1532. xy_char_put_1:
  1533.     mov    ah,0
  1534.     call    xychrout
  1535.     inc    dh
  1536. xy_char_put_4:
  1537.     ret
  1538.  
  1539.  
  1540.     public    prevline
  1541. prevline:
  1542. ;retreat si to the previous line.
  1543. ;return zr if si->beginning of file (and leave si alone)
  1544. ;return nz otherwise.
  1545.  
  1546. ;are we at the beginning of the file already?
  1547.     cmp    si,toptop
  1548.     je    prevline_beginning    ;yes - exit.
  1549.  
  1550. ;where are we in the file?
  1551.     cmp    si,topbot        ;at, before or after the point?
  1552.     jbe    prevline_before
  1553. prevline_after:
  1554.     dec    si
  1555.     cmp    si,bottop        ;have we reached the top of the bottom?
  1556.     je    prevline_at        ;yes - drop down to prevline_before.
  1557.     cmp    [si-2].w,LINENEW    ;at the beginning of a new line?
  1558.     jne    prevline_after        ;no - keep looking.
  1559.     dec    si            ;did we just find a non-real newline?
  1560.     cmp    si,bottop        ;if we did, then si is now at bottop
  1561.     je    prevline_at        ;  and we need to keep searching.
  1562.     inc    si            ;restore si and exit.
  1563.     jmp    short prevline_exit
  1564.  
  1565. prevline_at:
  1566.     mov    si,topbot        ;start searching at the bottom
  1567.     inc    si            ;  of the top.
  1568. prevline_before:
  1569.     dec    si
  1570.     cmp    [si-2].w,LINENEW    ;at the beginning of a new line?
  1571.     jne    prevline_before        ;no - keep looking.
  1572. prevline_exit:
  1573.     or    si,si            ;return nz
  1574. prevline_beginning:
  1575.     ret
  1576.  
  1577.  
  1578.     public    nextline
  1579. nextline:
  1580. ;advance si to the next line.
  1581. ;return zr if si->end of file (and leave si alone)
  1582. ;return nz otherwise.
  1583.     cmp    si,topbot
  1584.     jne    nextline_1
  1585.     mov    si,bottop
  1586. nextline_1:
  1587.     cmp    si,botbot
  1588.     je    nextline_2
  1589.     cmp    [si].w,LINENEW
  1590.     je    nextline_3
  1591.     inc    si
  1592.     jmp    nextline
  1593. nextline_3:
  1594.     add    si,2
  1595.     or    si,si
  1596.     ret
  1597. nextline_2:
  1598.     push    ax
  1599.     xor    ax,ax
  1600.     pop    ax
  1601.     ret
  1602.  
  1603.  
  1604.     public    compute_one
  1605. compute_one:
  1606.     cmp    al,HT
  1607.     jne    compute_one_1
  1608.     and    dl,0f8h
  1609.     add    dx,008h
  1610.     ret
  1611. compute_one_1:
  1612.     inc    dx
  1613.     ret
  1614.  
  1615.  
  1616. code    ends
  1617.  
  1618.     end
  1619.